<?php
namespace app\common\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;

use app\common\model as M;
use service\JiciWechatService;
/**
 * 提现自动到帐
 */
class Autowithdraw extends Command
{
    protected function configure()
    {
        $this->setName('autowithdraw')
            ->setDescription('提现自动到帐，支持微信自动付款，支付宝暂不支持');
    }

    /**
     * [execute description]
     * @Author   FW
     * @DateTime 2021-06-21
     * @Email    123763712@qq.com
     * @param    Input            $input  [description]
     * @param    Output           $output [description]
     * @return   [type]                   [description]
     */
    protected function execute(Input $input, Output $output)
    {
        M\Withdraw::startTrans();

        try {
            $this->_platformCheck();

            foreach ( $this->_getTasks() as $task ) {
                if ( empty($task) ) break;

                $this->_processTask($task);
            }
        } catch ( \Exception $e ) {
            M\Withdraw::rollbackTrans();

            $error = json_encode([
                'file'    =>    $e->getFile(),
                'line'    =>    $e->getLine(),
                'msg'     =>    $e->getMessage()
            ]);
            return $output->writeln(sprintf('执行失败[%s]。时间：%s' , $error , date('Y-m-d H:i:s')) );
        }

        M\Withdraw::commit();
        return $output->writeln('执行成功。时间：'  . date('Y-m-d H:i:s'));
    }

    /**
     * 平台检查
     * 当天总提现笔数和总提现金额是否超出预警
     * @Author   FW
     * @DateTime 2021-06-21
     * @Email    123763712@qq.com
     * @return   [type]           [description]
     */
    private function _platformCheck()
    {
        $day_total_amt = M\Withdraw::where(['audit_type'=>1,'status' => 3])->where('receipt_time','BETWEEN',[date('Y-m-d 00:00:00') , date('Y-m-d 23:59:59')])->sum('amount');
        if ( $day_total_amt > M\Withdraw::DAY_MAX_AMOUNT ) throw new \Exception('超出当天平台最大提现总额');

        $day_total_nums = M\Withdraw::where(['audit_type'=>1,'status' => 3])->where('receipt_time','BETWEEN',[date('Y-m-d 00:00:00') , date('Y-m-d 23:59:59')])->count();
        if ( $day_total_nums > M\Withdraw::DAY_MAX_TRANS ) throw new \Exception('超出当天平台最大提现总额');
    }

    /**
     * 获取任务
     * @Author   FW
     * @DateTime 2021-07-05
     * @Email    123763712@qq.com
     * @return   [type]           [description]
     */
    private function _getTasks ( $task_nums = 20 )
    {
        for ( $i=0 ; $i <= $task_nums; $i++ ) {
            yield M\Withdraw::where(['status' => 1 ,'audit_type' => 0,'is_del' => 0])->find();
        }
    }

    /**
     * 处理单条任务
     * @Author   FW
     * @DateTime 2021-07-05
     * @Email    123763712@qq.com
     * @param    [type]           $task [description]
     * @return   [type]                 [description]
     */
    private function _processTask ( $task )
    {
        ## 01检查机构资金余额
        $org_info = M\Organ::withAccount($task->wd_type , $task->org_id);
        if ( !$org_info )
            throw new \Exception('任务处理失败【0091】');

        // 这个是机构实时余额，此时检查可能导致最后一笔提现无法完成
        // if ( $org_info->organ_balance < $task->amount )
        //     throw new \Exception('任务处理失败【0092】');

        if ( !$org_info->wd_reciver_account  )
            throw new \Exception('任务处理失败【0093】');

        $pay_result = ['code' => 500];
        if ( $task->wd_type == 'wechat' ) {
            $pay_result = $this->_wechatPay($org_info->wd_reciver_account , $task->amount , $org_info->wd_reciver_realname);
        }

        if ( $pay_result['code'] == 200 ) {
            ## 回写提现记录:成功
            $res = M\Withdraw::where('id' , $task->id)->update([
                'audit_time'      =>    date('Y-m-d H:i:s'),
                'receipt_time'    =>    date('Y-m-d H:i:s'),
                'receipt_account' =>    $org_info->wd_reciver_account,
                'audit_type'      =>    1,
                'audit_user'      =>    'SYSTEM',
                'status'          =>    3,
                'transaction_seq' =>    $pay_result['data']['transaction_seq'] ?? ''
            ]);
            if ( $res === false ) throw new \Exception('任务处理失败【0094】');
        }

        if ( $pay_result['code'] == 500 ) {
            ## 回写提现记录：失败
            $res = M\Withdraw::where('id' , $task->id)->update([
                'audit_time'      =>    date('Y-m-d H:i:s'),
                'receipt_account' =>    $org_info->wd_reciver_account,
                'audit_type'      =>    1,
                'audit_user'      =>    'SYSTEM',
                'status'          =>    4,
                'transaction_seq' =>    $pay_result['data']['transaction_seq'] ?? '',
                's4_reason'       =>    $pay_result['msg'] ?? '提现失败'
            ]);

            if ( $res !== false ) {
                $res = M\Organ::where('id' , $task->org_id)->setInc('organ_balance' , $task->amount);
            }
            if ( $res === false ) throw new \Exception('任务处理失败【0095】');
        }
    }

    /**
     * 微信付款给个人
     * @Author   FW
     * @DateTime 2021-07-05
     * @Email    123763712@qq.com
     * @param    [type]           $openid [description]
     * @param    [type]           $amount [description]
     * @return   [type]                   [description]
     */
    private function _wechatPay ($openid , $amount, $realname)
    {
        $transaction_seq = M\Withdraw::createWithdrawTransacSeq('WX');
        $request = JiciWechatService::PayPersonal($transaction_seq,$openid, $amount, $realname, 'FORCE_CHECK', '机构提现到帐');
        if ($request->return_code == 'SUCCESS' && $request->result_code == 'SUCCESS') {
            return [
                'code'    =>    200,
                'msg'     =>    'SUCCESS', 
                'data'    =>    [
                    'transaction_seq'    =>    $transaction_seq
                ]
            ];
        }
        return [
            'code'    =>    500,
            'msg'     =>    $request->return_msg,
            'data'    =>    [
                'transaction_seq'    =>    $transaction_seq
            ]
        ];
    }
}// Class End